<template>
	<view>
		<slot />
		<x-popup v-model="show" :height="props.height" :clickMaskHide="props.clickMaskHide">
			<view class="flex flex-center grid-gap-4">
				<text class="h9 p-4 " :style="[props.cancelColor ? `color:${props.cancelColor}` : 'color:var(--xl-dark-light-7)']" @tap="cancel">
					{{ props.cancelText }}
				</text>
				<view class="flex-1">{{ props.title }}</view>
				<text class="h9 p-4 " :style="[props.confirmColor ? `color:${props.confirmColor}` : '']" @tap="confirm">
					{{ props.confirmText }}
				</text>
			</view>
			<picker-view v-if="showPricker" class="flex-1 bg" :value="value" @change="bindChange"
				indicator-style="height:50px;">
				<template v-if="props.columns.length">
					<picker-view-column v-for="(child, index) in props.columns" :key="index">
						<view class="flex flex-center" v-for="(item, childIndex) in child" :key="childIndex">
							<text class="h9 font-weight-600">
								{{ item[props.keyName] }}
							</text>
						</view>
					</picker-view-column>
				</template>
				<template v-else-if="['date', 'year', 'month', 'time', 'datetime'].includes(props.mode)">
					<picker-view-column v-for="(child, index) in dateColumns" :key="index">
						<view class="flex flex-center" v-for="(item, childIndex) in child" :key="childIndex">
							<text class="h9 font-weight-600">
								{{ item.label }}
							</text>
						</view>
					</picker-view-column>
				</template>
			</picker-view>
			<view class="pb-safe-area"></view>
		</x-popup>
	</view>
</template>

<script setup lang="ts">
import { ref, watchEffect, watch, defineProps, onMounted, nextTick } from 'vue';
const props = withDefaults(defineProps<{
	modelValue?: any
	show: boolean
	mode?: 'date' | 'year' | 'month' | 'time' | 'datetime'
	columns?: any
	keyName?: string
	valueName?: string
	title?: string
	cancelColor?: string
	confirmColor?: string
	cancelText?: string
	confirmText?: string
	minDate?: Date | number | string
	maxDate?: Date | number | string
	height?: string
	clickMaskHide?: boolean
}>(), {
	show: false,
	columns: [],
	keyName: 'label',
	valueName: 'value',
	title: '',
	cancelText: '取消',
	confirmText: '确定',
	cancelColor: '',
	confirmColor: '',
	mode: 'date',
	height: '300px',
	clickMaskHide: false
});
const show = ref(props.show)
const showPricker = ref(false)
const dateColumns = ref([])
const value = ref(new Array(props.columns.length).fill(0))
const emit = defineEmits(['cancel', 'confirm', 'update:modelValue', 'update:show'])
const dataValue = ref<any>(props.modelValue)
const selected = ref<any>();
const initDate = () => {
	if (!value.value.length) {
		value.value = [0, 0, 0];
	}
	const maxDate = props.maxDate instanceof Date ? props.maxDate : new Date(props.maxDate);
	const minDate = props.minDate instanceof Date ? props.minDate : new Date(props.minDate);
	const columns: any = [
		[],
		[],
		[]
	]
	const maxYear = maxDate.getFullYear();
	const minYear = minDate.getFullYear();
	for (let i = maxYear; i > minYear; i--) {
		const date = new Date();
		date.setFullYear(i);
		columns[0].push({
			label: date.getFullYear() + '年',
			value: date.getFullYear()
		})
	}
	const selectedYear = columns[0][value.value[0]].value;
	const maxMonth = maxDate.getMonth();
	const minMonth = minDate.getMonth();
	for (let i = 12; i > 0; i--) {
		if (selectedYear === maxYear && i - 1 > maxMonth) {
			continue;
		}
		if (selectedYear === minYear && i - 1 < minMonth) {
			continue;
		}
		columns[1].push({
			label: i + '月',
			value: i
		})
	}
	const date = new Date();
	date.setFullYear(selectedYear);
	let monthIndex = value.value[1];
	if (monthIndex > columns[1].length - 1) {
		monthIndex = 0;
	}
	const selectedMonth = columns[1][monthIndex].value;
	date.setMonth(selectedMonth);
	const maxDay = maxDate.getDate();
	const minDay = minDate.getDate();
	date.setDate(1);
	date.setHours(0);
	date.setMinutes(0);
	date.setSeconds(0);
	date.setHours(date.getHours() - 1);
	const monthMaxDay = date.getDate();
	for (let i = monthMaxDay; i > 0; i--) {
		if (selectedYear === maxYear && selectedMonth === maxMonth + 1 && i > maxDay) {
			continue;
		}
		if (selectedYear === minYear && selectedMonth === minMonth + 1 && i < minDay) {
			continue;
		}
		columns[2].push({
			label: i + '日',
			value: i
		})
	}
	dateColumns.value = columns
	showPricker.value = true
	value.value[1] = monthIndex;
	const selectedDate = new Date();
	selectedDate.setFullYear(dateColumns.value[0][value.value[0]].value);
	selectedDate.setMonth(dateColumns.value[1][monthIndex].value - 1);
	let dayIndex = value.value[2];
	if (dayIndex > columns[2].length - 1) {
		dayIndex = 0;
		value.value[2] = dayIndex;
	}
	selectedDate.setDate(dateColumns.value[2][dayIndex].value);
	if (props.modelValue instanceof Date) {
		dataValue.value = selectedDate;
	} else if (typeof props.modelValue === 'string') {
		dataValue.value = `${selectedDate.getFullYear()}-${selectedDate.getMonth() + 1}-${selectedDate.getDate()}`;
	} else if (typeof props.modelValue === 'number') {
		dataValue.value = selectedDate.getTime();
	}
	selected.value = selectedDate;
}
const initYear = () => {
	if (!value.value.length) {
		value.value = [0];
	}
	const maxDate = props.maxDate instanceof Date ? props.maxDate : new Date(props.maxDate);
	const minDate = props.minDate instanceof Date ? props.minDate : new Date(props.minDate);
	const columns: any = [
		[]
	]
	const maxYear = maxDate.getFullYear();
	const minYear = minDate.getFullYear();
	for (let i = maxYear; i > minYear; i--) {
		const date = new Date();
		date.setFullYear(i);
		columns[0].push({
			label: date.getFullYear() + '年',
			value: date.getFullYear()
		})
	}
	dateColumns.value = columns
	showPricker.value = true
	const selectedYear = dateColumns.value[0][value.value[0]].value;
	const selectedDate = new Date();
	selectedDate.setFullYear(selectedYear);
	if (props.modelValue instanceof Date) {
		dataValue.value = selectedDate;
	} else if (typeof props.modelValue === 'string') {
		dataValue.value = `${selectedDate.getFullYear()}`;
	} else if (typeof props.modelValue === 'number') {
		dataValue.value = selectedDate.getTime();
	}
	selected.value = selectedDate;
}
const initMonth = () => {
	if (!value.value.length) {
		value.value = [0, 0];
	}
	const maxDate = props.maxDate instanceof Date ? props.maxDate : new Date(props.maxDate);
	const minDate = props.minDate instanceof Date ? props.minDate : new Date(props.minDate);
	const columns: any = [
		[],
		[]
	]
	const maxYear = maxDate.getFullYear();
	const minYear = minDate.getFullYear();
	for (let i = maxYear; i > minYear; i--) {
		const date = new Date();
		date.setFullYear(i);
		columns[0].push({
			label: date.getFullYear() + '年',
			value: date.getFullYear()
		})
	}
	const selectedYear = columns[0][value.value[0]].value;
	const maxMonth = maxDate.getMonth();
	const minMonth = minDate.getMonth();
	for (let i = 12; i > 0; i--) {
		if (selectedYear === maxYear && i - 1 > maxMonth) {
			continue;
		}
		if (selectedYear === minYear && i - 1 < minMonth) {
			continue;
		}
		columns[1].push({
			label: i + '月',
			value: i
		})
	}
	dateColumns.value = columns
	showPricker.value = true
	let monthIndex = value.value[1];
	if (monthIndex > columns[1].length - 1) {
		monthIndex = 0;
		value.value[1] = monthIndex;
	}
	const selectedDate = new Date();
	selectedDate.setFullYear(dateColumns.value[0][value.value[0]].value);
	selectedDate.setMonth(dateColumns.value[1][monthIndex].value - 1);
	if (props.modelValue instanceof Date) {
		dataValue.value = selectedDate;
	} else if (typeof props.modelValue === 'string') {
		dataValue.value = `${selectedDate.getFullYear()}-${selectedDate.getMonth() + 1}`;
	} else if (typeof props.modelValue === 'number') {
		dataValue.value = selectedDate.getTime();
	}
	selected.value = selectedDate;
}
const initTime = () => {
	if (!value.value.length) {
		value.value = [0, 0];
	}
	const columns: any = [
		[],
		[]
	]
	for (let i = 0; i < 24; i++) {
		columns[0].push({
			label: i + '时',
			value: i
		})
	}
	for (let i = 0; i < 60; i++) {
		columns[1].push({
			label: i + '分',
			value: i
		})
	}
	dateColumns.value = columns
	showPricker.value = true
	const selectedDate = new Date();
	selectedDate.setHours(dateColumns.value[0][value.value[0]].value);
	selectedDate.setMinutes(dateColumns.value[1][value.value[1]].value);
	if (props.modelValue instanceof Date) {
		dataValue.value = selectedDate;
	} else if (typeof props.modelValue === 'string') {
		dataValue.value = `${selectedDate.getHours()}:${selectedDate.getMinutes()}`;
	} else if (typeof props.modelValue === 'number') {
		dataValue.value = selectedDate.getTime();
	}
	selected.value = selectedDate;
}
const initDateTime = () => {
	if (!value.value.length) {
		value.value = [0, 0, 0, 0, 0, 0];
	}
	const maxDate = props.maxDate instanceof Date ? props.maxDate : new Date(props.maxDate);
	const minDate = props.minDate instanceof Date ? props.minDate : new Date(props.minDate);
	const columns: any = [
		[],
		[],
		[],
		[],
		[],
		[]
	]
	const maxYear = maxDate.getFullYear();
	const minYear = minDate.getFullYear();
	for (let i = maxYear; i > minYear; i--) {
		const date = new Date();
		date.setFullYear(i);
		columns[0].push({
			label: date.getFullYear() + '年',
			value: date.getFullYear()
		})
	}
	const selectedYear = columns[0][value.value[0]].value;
	const maxMonth = maxDate.getMonth();
	const minMonth = minDate.getMonth();
	for (let i = 12; i > 0; i--) {
		if (selectedYear === maxYear && i - 1 > maxMonth) {
			continue;
		}
		if (selectedYear === minYear && i - 1 < minMonth) {
			continue;
		}
		columns[1].push({
			label: i + '月',
			value: i
		})
	}
	const date = new Date();
	date.setFullYear(selectedYear);
	let monthIndex = value.value[1];
	if (monthIndex > columns[1].length - 1) {
		monthIndex = 0;
	}
	const selectedMonth = columns[1][monthIndex].value;
	date.setMonth(selectedMonth);
	const maxDay = maxDate.getDate();
	const minDay = minDate.getDate();
	date.setDate(1);
	date.setHours(0);
	date.setMinutes(0);
	date.setSeconds(0);
	date.setHours(date.getHours() - 1);
	const monthMaxDay = date.getDate();
	for (let i = monthMaxDay; i > 0; i--) {
		if (selectedYear === maxYear && selectedMonth === maxMonth + 1 && i > maxDay) {
			continue;
		}
		if (selectedYear === minYear && selectedMonth === minMonth + 1 && i < minDay) {
			continue;
		}
		columns[2].push({
			label: i + '日',
			value: i
		})
	}
	date.setDate(columns[2][value.value[2]].value);
	const selectedDate = new Date();
	selectedDate.setFullYear(columns[0][value.value[0]].value);
	selectedDate.setMonth(columns[1][monthIndex].value - 1);
	let dayIndex = value.value[2];
	if (dayIndex > columns[2].length - 1) {
		dayIndex = 0;
	}
	selectedDate.setDate(columns[2][dayIndex].value);
	const maxHour = maxDate.getHours();
	const minHour = minDate.getHours();
	for (let i = 24; i > 0; i--) {
		if (selectedYear === maxYear && selectedMonth === maxMonth + 1 && selectedDate.getDate() === maxDay && i - 1 > maxHour) {
			continue;
		}
		if (selectedYear === minYear && selectedMonth === minMonth + 1 && selectedDate.getDate() === minDay && i - 1 < minHour) {
			continue;
		}
		columns[3].push({
			label: i - 1 + '时',
			value: i - 1
		})
	}
	let hourIndex = value.value[3];
	if (hourIndex > columns[3].length - 1) {
		hourIndex = 0;
	}
	const selectedHour = columns[3][hourIndex].value;
	selectedDate.setHours(selectedHour);
	const maxMinute = maxDate.getMinutes();
	const minMinute = minDate.getMinutes();
	for (let i = 60; i > 0; i--) {
		if (selectedYear === maxYear && selectedMonth === maxMonth + 1 && selectedDate.getDate() === maxDay && selectedHour === maxHour && i - 1 > maxMinute) {
			continue;
		}
		if (selectedYear === minYear && selectedMonth === minMonth + 1 && selectedDate.getDate() === minDay && selectedHour === minHour && i - 1 < minMinute) {
			continue;
		}
		columns[4].push({
			label: i - 1 + '分',
			value: i - 1
		})
	}
	let minuteIndex = value.value[4];
	if (minuteIndex > columns[4].length - 1) {
		minuteIndex = 0;
	}
	const selectedMinute = columns[4][minuteIndex].value;
	selectedDate.setMinutes(selectedMinute);
	const maxSecond = maxDate.getSeconds();
	const minSecond = minDate.getSeconds();
	for (let i = 60; i > 0; i--) {
		if (selectedYear === maxYear && selectedMonth === maxMonth + 1 && selectedDate.getDate() === maxDay && selectedHour === maxHour && selectedMinute === maxMinute && i - 1 > maxSecond) {
			continue;
		}
		if (selectedYear === minYear && selectedMonth === minMonth + 1 && selectedDate.getDate() === minDay && selectedHour === minHour && selectedMinute === minMinute && i - 1 < minSecond) {
			continue;
		}
		columns[5].push({
			label: i - 1 + '秒',
			value: i - 1
		})
	}
	dateColumns.value = columns
	showPricker.value = true
	value.value[1] = monthIndex;
	value.value[2] = dayIndex;
	value.value[3] = hourIndex;
	value.value[4] = minuteIndex;
	let secondIndex = value.value[5];
	if (secondIndex > columns[5].length - 1) {
		secondIndex = 0;
		value.value[5] = secondIndex;
	}
	const selectedSecond = columns[5][secondIndex].value;
	selectedDate.setSeconds(selectedSecond);
	if (props.modelValue instanceof Date) {
		dataValue.value = selectedDate;
	} else if (typeof props.modelValue === 'string') {
		dataValue.value = `${selectedDate.getFullYear()}-${selectedDate.getMonth() + 1}-${selectedDate.getDate()} ${selectedDate.getHours()}:${selectedDate.getMinutes()}:${selectedDate.getSeconds()}`;
	} else if (typeof props.modelValue === 'number') {
		dataValue.value = selectedDate.getTime();
	}
	selected.value = selectedDate;
}
const initColumns = () => {
	if (props.columns.length) {
		nextTick(() => {
			showPricker.value = true
		})
	} else {
		switch (props.mode) {
			case 'date':
				initDate();
				break;
			case 'year':
				initYear();
				break;
			case 'month':
				initMonth();
				break;
			case 'time':
				initTime();
				break;
			case 'datetime':
				initDateTime();
				break;
		}
	}
}
const bindChange = (e: any) => {
	value.value = e.detail.value
	if (props.columns.length) {
		const data = props.columns.map((item: any, index: number) => {
			return item[e.detail.value[index]]
		}).filter((item: any) => item)
		if(data.length<=0){
			return
		}
		if (Array.isArray(props.modelValue)) {
			dataValue.value = data.map((item: any) => item[props.valueName])
			selected.value = data
		} else {
			dataValue.value = data[0][props.valueName]
			selected.value = data[0]
		}
	} else {
		initColumns();
	}
}
const cancel = () => {
	emit('cancel')
	emit('update:show', false)
}
const confirm = () => {
	bindChange({
		detail: value
	})
	emit('update:modelValue', dataValue.value)
	emit('confirm', selected.value)
	emit('update:show', false)
}
const initModelValue = (val:any) => {
	if (val) {
		if (props.columns.length) {
			if (Array.isArray(val)) {
				value.value = val.map((item: any, index: number) => {
					const i=props.columns[index].findIndex((child: any) => child[props.valueName] === item);
					return i>=0?i:0
				})
			} else {
				const i=props.columns[0].findIndex((child: any) => child[props.valueName] === val);
				value.value[0] = i>=0?i:0
			}
		} else {
			let date: Date;
			if (val instanceof Date) {
				date = val;
			} else if (typeof val === 'string') {
				// 判断并补全时间格式 YYYY-mm-dd HH:ii:ss
				const arr = val.split(' ');
				let dateArr = [1970, 1, 1];
				if (arr[0]) {
					arr[0].split('-').forEach((item, index) => {
						dateArr[index] = Number(item);
					})
				}
				let timeArr = [0, 0, 0];
				if (arr[1]) {
					arr[1].split(':').forEach((item, index) => {
						timeArr[index] = Number(item);
					})
				}
				date = new Date();
				date.setFullYear(Number(dateArr[0]));
				date.setMonth(Number(dateArr[1]) - 1);
				date.setDate(Number(dateArr[2]));
				date.setHours(Number(timeArr[0]));
				date.setMinutes(Number(timeArr[1]));
				date.setSeconds(Number(timeArr[2]));
			} else if (typeof val === 'number') {
				date = new Date(val);
			}
			value.value[0] = dateColumns.value[0].findIndex((item: any) => item.value === date.getFullYear())
			initColumns();
			for (let i = 1; i < dateColumns.value.length; i++) {
				switch (i) {
					case 1:
						value.value[i] = dateColumns.value[i].findIndex((item: any) => item.value === date.getMonth() + 1)
						break;
					case 2:
						value.value[i] = dateColumns.value[i].findIndex((item: any) => item.value === date.getDate())
						break;
					case 3:
						value.value[i] = dateColumns.value[i].findIndex((item: any) => item.value === date.getHours())
						break;
					case 4:
						value.value[i] = dateColumns.value[i].findIndex((item: any) => item.value === date.getMinutes())
						break;
					case 5:
						value.value[i] = dateColumns.value[i].findIndex((item: any) => item.value === date.getSeconds())
						break;
				}
				initColumns();
			}
		}
	}
}

watchEffect(() => {
	show.value = props.show
	if (props.columns.length) {
		initColumns()
	}
})
watch(() => props.modelValue, initModelValue)
onMounted(() => {
	initColumns();
	initModelValue(props.modelValue)
})
</script>

<style lang="scss"></style>